package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTemplateEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTemplateNodeEntity;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.ProcessOpenDTO;
import com.xbongbong.paas.pojo.dto.ProcessTemplateNodeAddDTO;
import com.xbongbong.paas.pojo.dto.ProcessUpdateDTO;
import com.xbongbong.paas.service.PaasProcessTemplateNodeService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 流程节点操作实现类
 * @author wufeng
 * @date 2018/8/21 17:41
 */
@Service("paasProcessTemplateNodeService")
public class PaasProcessTemplateNodeServiceImpl implements PaasProcessTemplateNodeService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasProcessTemplateNodeServiceImpl.class);

    private static final String PROCESS_START_UID = "startNode";

    private static final Double PROCESS_START_Y = 50D;

    private static final String PROCESS_END_UID = "endNode";

    private static final Double PROCESS_END_Y = 350D;
    @Resource
    private PaasProcessTemplateNodeModel processTemplateNodeModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private CommonHelp commonHelp;

    /**
     * 初始化流程节点--增加开始节点，结束节点
     * @param processOpenDTO
     * @param paasProcessTemplateEntity
     * @throws XbbException
     */
    @Override
    public void insertInitProcessTemplateNode(ProcessOpenDTO processOpenDTO, PaasProcessTemplateEntity paasProcessTemplateEntity) throws XbbException{
        try {
            // 保存流程结束节点
            Long formId = paasProcessTemplateEntity.getFormId();
            String corpid = paasProcessTemplateEntity.getCorpid();
            List<FieldAttrEntity> explainList;
            List<SummaryDataPoJo> summaryList = null;
            String formName = null;
            if (Objects.equals(paasProcessTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(formId, corpid);
                explainList = JSONArray.parseArray(workOrderExplainEntityExt.getExplains(), FieldAttrEntity.class);
                WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpid);
                if (workOrderEntity != null) {
                    summaryList = JSONArray.parseArray(workOrderEntity.getSummary(), SummaryDataPoJo.class);
                    formName = workOrderEntity.getName();
                }
            } else {
                PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
                explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                PaasFormEntityExt paasFormEntity = paasFormModel.getByKey(formId, corpid);
                if (paasFormEntity != null) {
                    summaryList = JSONArray.parseArray(paasFormEntity.getSummary(), SummaryDataPoJo.class);
                    formName = paasFormEntity.getName();
                }
            }
            ProcessTemplateNodeAddDTO processTemplateNodeAddDTO = new ProcessTemplateNodeAddDTO();
            processTemplateNodeAddDTO.setType(NodeTypeEnum.START_PROCESS_NODE.getNodeType());
            processTemplateNodeAddDTO.setName(I18nMessageUtil.getMessage(I18nStringConstant.PROCESS_START_NAME));
            PaasProcessTemplateNodeEntity processTemplateNodeEntity = new PaasProcessTemplateNodeEntity();
            BeanUtils.copyProperties(processTemplateNodeAddDTO, processTemplateNodeEntity);
            processTemplateNodeEntity.setCorpid(processOpenDTO.getCorpid());
            processTemplateNodeEntity.setAppId(processOpenDTO.getAppId());
            processTemplateNodeEntity.setMenuId(processOpenDTO.getMenuId());
            processTemplateNodeEntity.setFormId(processOpenDTO.getFormId());
            processTemplateNodeEntity.setTemplateId(paasProcessTemplateEntity.getId());
            processTemplateNodeEntity.setUid(PROCESS_START_UID);
            processTemplateNodeEntity.setY(PROCESS_START_Y);
            //新模板用
            if (Objects.equals(processOpenDTO.getType(), 2)) {
                processTemplateNodeEntity.setPrevId(BasicConstant.ZERO.toString());
            }
            // 数据库不允许插入空值
            processTemplateNodeEntity.setMainUser(JSONArray.toJSONString(processTemplateNodeAddDTO.getMainUser()));
            processTemplateNodeEntity.setCcUser(JSONArray.toJSONString(processTemplateNodeAddDTO.getCcUser()));
            processTemplateNodeEntity.setTransferUser(JSONArray.toJSONString(processTemplateNodeAddDTO.getTransferUser()));
            processTemplateNodeEntity.setBackNode(JSONArray.toJSONString(processTemplateNodeAddDTO.getBackNode()));
            processTemplateNodeEntity.setCreatorId(processOpenDTO.getUserId());
            JSONArray explainArray = new JSONArray();
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(processOpenDTO.getBusinessType());
            // 这个特殊操作简直了
            List<Integer> showTypeList = commonHelp.processShowAttrFieldType();
            List<String> specialContractAttrList = Arrays.asList(ContractEnum.CONTRACT_COST.getAttr(), ContractEnum.GROSS_PROFIT.getAttr(), ContractEnum.GROSS_PROFIT_RATE.getAttr(),
                    ContractEnum.CASH_PROFIT.getAttr(), ContractEnum.CASH_PROFIT_RATE.getAttr());
            List<String> specialOpportunityAttrList = Arrays.asList(SalesOpportunityEnum.COST.getAttr(), SalesOpportunityEnum.GROSS_PROFIT.getAttr(), SalesOpportunityEnum.GROSS_PROFIT_RATE.getAttr());
            for (FieldAttrEntity item : explainList) {
                Integer editable = item.getEditable();
                // 字段是否开启
                if (Objects.equals(item.getVisible(), 0) || Objects.equals(item.getIsOpen(), 0)) {
                    continue;
                }
                if (Objects.equals(item.getIsRedundant(), 0)) {
                    // 是否在设计阶段展示
                    // 0:全部显示 1:新建编辑显示 4:新建编辑，列表显示 5:新建编辑，详情显示
                    if (commonHelp.processNotShow(item.getEditHide(), item.getShowType(), showTypeList)) {
                        continue;
                    }
                    editable = setSpecialEditable(item.getAttr(), item.getFieldType(), editable, xbbRefTypeEnum, specialContractAttrList, specialOpportunityAttrList);
                }
                int summary = 0;
                if (summaryList != null && summaryList.size() != 0) {
                    for (SummaryDataPoJo summaryDataPoJo : summaryList) {
                        if (Objects.equals(summaryDataPoJo.getAttr(), item.getAttr())) {
                            summary = 1;
                            break;
                        }
                    }
                }
                explainArray.add(new FieldPermissionEntityExt(item.getAttr(), item.getFieldType(), editable, 1, summary));
                if (Objects.equals(item.getFieldType(), FieldTypeEnum.SUB_FORM.getType()) || Objects.equals(item.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())) {
                    List<? extends FieldAttrEntity> subExplainList = item.getSubForm().getItems();
                    subExplainList.forEach((subItem)-> explainArray.add(new FieldPermissionEntityExt(item.getAttr(), subItem.getAttr(), item.getFieldType(), 1, 1, 0)));
                }
            }
            processTemplateNodeEntity.setFieldPermission(JSONArray.toJSONString(explainArray));
            processTemplateNodeModel.insert(processTemplateNodeEntity);
            // 记录日志
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_PROCESS_TEMPLATE_NODE),
                    processOpenDTO.getLoginUserName(), formName);
            mongoLogHelp.buildLog(processOpenDTO.getCorpid(), processOpenDTO.getUserId(), processOpenDTO.getLoginUserName(),
                    OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE_NODE, OperateTypeEnum.NEW, formId.toString(),
                    formName, memo, processOpenDTO.getHttpHeader());

            if (Objects.equals(processOpenDTO.getType(), 1)) {
                // 保存流程结束节点
                processTemplateNodeEntity.setId(null);
                processTemplateNodeEntity.setType(NodeTypeEnum.END_PROCESS_NODE.getNodeType());
                processTemplateNodeEntity.setName(I18nMessageUtil.getMessage(I18nStringConstant.PROCESS_END_NAME));
                processTemplateNodeEntity.setUid(PROCESS_END_UID);
                processTemplateNodeEntity.setY(PROCESS_END_Y);
                processTemplateNodeModel.insert(processTemplateNodeEntity);
                // 记录日志
                memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_PROCESS_TEMPLATE_NODE), processOpenDTO.getLoginUserName(),
                        formName);
                mongoLogHelp.buildLog(processOpenDTO.getCorpid(), processOpenDTO.getUserId(), processOpenDTO.getLoginUserName(),
                        OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE_NODE, OperateTypeEnum.NEW, formId.toString(),
                        formName, memo, processOpenDTO.getHttpHeader());
            }
        } catch (Exception e){
            LOG.error("PaasProcessTemplateNodeService数据库初始化流程节点出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void nodeOperate(List<PaasProcessTemplateNodeEntityExt> nodeEntityAddList, List<PaasProcessTemplateNodeEntityExt> nodeEntityUpdateList,
                            List<PaasProcessTemplateNodeEntityExt> nodeEntityDeleteList, PaasProcessTemplateEntity processTemplateEntity, ProcessUpdateDTO processUpdateDTO) throws XbbException {
        try {
            String userId = processUpdateDTO.getUserId();
            String userName = processUpdateDTO.getLoginUserName();
            String corpid = processUpdateDTO.getCorpid();
            Long formId = processUpdateDTO.getFormId();
            String formName = "";
            if (Objects.equals(processTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpid);
                if (workOrderEntity != null) {
                    formName = workOrderEntity.getName();
                }
            } else {
                PaasFormEntityExt paasFormEntity = paasFormModel.getByKey(formId, corpid);
                if (paasFormEntity != null) {
                    formName = paasFormEntity.getName();
                }
            }
            // 批量增加节点
            if (!nodeEntityAddList.isEmpty()) {
                processTemplateNodeModel.insertBatch(nodeEntityAddList);
                // 记录日志
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_BATCH_PROCESS_TEMPLATE_NODE), userName, formName);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE_NODE,
                        OperateTypeEnum.NEW, formId.toString(), formName, memo, processUpdateDTO.getHttpHeader());
            }
            // 批量更新
            if (!nodeEntityUpdateList.isEmpty()) {
                processTemplateNodeModel.updateBatch(nodeEntityUpdateList, corpid);
                // 记录日志
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_BATCH_PROCESS_TEMPLATE_NODE), userName, formName);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE_NODE,
                        OperateTypeEnum.EDIT, formId.toString(), formName, memo, processUpdateDTO.getHttpHeader());
            }
            // 批量删除
            if (!nodeEntityDeleteList.isEmpty()) {
                processTemplateNodeModel.deleteBatch(nodeEntityDeleteList, corpid);
                // 记录日志
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_BATCH_PROCESS_TEMPLATE_NODE), userName, formName);
                mongoLogHelp.buildLog(corpid, processUpdateDTO.getUserId(), userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE_NODE,
                        OperateTypeEnum.DELETE, formId.toString(), formName, memo, processUpdateDTO.getHttpHeader());
            }
        }catch (Exception e) {
            LOG.error("批量操作流程节点出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private Integer setSpecialEditable(String attr, Integer fieldType, Integer editable, XbbRefTypeEnum xbbRefTypeEnum,
                                     List<String> specialContractAttrList, List<String> specialOpportunityAttrList) {
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                if (Objects.equals(fieldType, FieldTypeEnum.COUSERID.getType()) || Objects.equals(fieldType, FieldTypeEnum.OWNERID.getType()) || specialContractAttrList.contains(attr)) {
                    editable = 0;
                }
                break;
            case SALES_OPPORTUNITY:
                if (Objects.equals(fieldType, FieldTypeEnum.COUSERID.getType()) || Objects.equals(fieldType, FieldTypeEnum.OWNERID.getType()) || specialOpportunityAttrList.contains(attr)) {
                    editable = 0;
                }
                break;
            case CUSTOMER_MANAGEMENT:
            case REFUND:
            case PURCHASE:
            case BOM_BILL:
            case PRODUCTION_ORDER:
                if (Objects.equals(fieldType, FieldTypeEnum.COUSERID.getType()) || Objects.equals(fieldType, FieldTypeEnum.OWNERID.getType())) {
                    editable = 0;
                }
                break;
            case PAY_SHEET:
                if (Objects.equals(attr, PaySheetEnum.PAY_PLAN.getAttr())) {
                    editable = 0;
                }
                break;
            default:
                break;
        }
        return editable;
    }
}
